using System;
using System.Collections.Generic;
using ContentRenderingApi.Extender;
using Com.ContentRendering.Api.ParserEngine;
using ContentRenderingApi.Path;
using ContentRenderingApi.Skeleton;

namespace ContentRenderingApi.Configuration
{
    /// <summary/>
    public class TransformationConfiguration
    {
        private List<PreOverrideSkeleton> _preOverrideSkeletons;
        private List<PostOverrideSkeleton> _postOverrideSkeletons;
        private List<WildcardOverrideSkeleton> _wildcardOverrideSkeletons;
        private List<ConditionalFunctionSkeleton> _conditionalFunctionSkeletons;
        private List<FormattedOutputFunctionSkeleton> _outputFunctionSkeletons;
        private List<FormattedOutputsFunctionSkeleton> _outputsFunctionSkeletons;
        private List<ObserverFunctionSkeleton> _observerFunctionSkeletons;
        private List<LocalFormatterSkeleton> _localFormatterSkeletons;
        private List<GlobalFormatterSkeleton> _globalFormatterSkeletons;
        private List<SortSkeleton> _sortSkeletons;
        private List<SelfSortSkeleton> _selfSortSkeletons;
        private List<ChildSortSkeleton> _childSortSkeletons;

        /// <summary/>
        internal TransformationConfiguration()
        {
            this._preOverrideSkeletons = new List<PreOverrideSkeleton>();
            this._postOverrideSkeletons = new List<PostOverrideSkeleton>();
            this._wildcardOverrideSkeletons = new List<WildcardOverrideSkeleton>();
            this._conditionalFunctionSkeletons = new List<ConditionalFunctionSkeleton>();
            this._outputFunctionSkeletons = new List<FormattedOutputFunctionSkeleton>();
            this._outputsFunctionSkeletons = new List<FormattedOutputsFunctionSkeleton>();
            this._observerFunctionSkeletons = new List<ObserverFunctionSkeleton>();
            this._localFormatterSkeletons = new List<LocalFormatterSkeleton>();
            this._globalFormatterSkeletons = new List<GlobalFormatterSkeleton>();
            this._sortSkeletons = new List<SortSkeleton>();
            this._selfSortSkeletons = new List<SelfSortSkeleton>();
            this._childSortSkeletons = new List<ChildSortSkeleton>();
        }

        /// <summary/>
        internal List<PreOverrideSkeleton> PreOverrideSkeletons
        {
            get { return this._preOverrideSkeletons; }
        }

        /// <summary/>
        internal List<PostOverrideSkeleton> PostOverrideSkeletons
        {
            get { return this._postOverrideSkeletons; }
        }

        /// <summary/>
        internal List<WildcardOverrideSkeleton> WildcardOverrideSkeletons
        {
            get { return this._wildcardOverrideSkeletons; }
        }

        /// <summary/>
        internal List<ConditionalFunctionSkeleton> ConditionalFunctionSkeletons
        {
            get { return this._conditionalFunctionSkeletons; }
        }

        /// <summary/>
        internal List<FormattedOutputFunctionSkeleton> FormattedOutputFunctionSkeletons
        {
            get { return this._outputFunctionSkeletons; }
        }

        /// <summary/>
        internal List<FormattedOutputsFunctionSkeleton> FormattedOutputsFunctionSkeletons
        {
            get { return this._outputsFunctionSkeletons; }
        }

        /// <summary/>
        internal List<ObserverFunctionSkeleton> ObserverFunctionSkeletons
        {
            get { return this._observerFunctionSkeletons; }
        }

        /// <summary/>
        internal List<GlobalFormatterSkeleton> GlobalFormatterSkeletons
        {
            get { return this._globalFormatterSkeletons; }
        }

        /// <summary/>
        internal List<LocalFormatterSkeleton> LocalFormatterSkeletons
        {
            get { return this._localFormatterSkeletons; }
        }

        /// <summary/>
        internal List<SelfSortSkeleton> SelfSortSkeletons
        {
            get { return this._selfSortSkeletons; }
        }

        /// <summary/>
        internal List<SortSkeleton> SortSkeletons
        {
            get { return this._sortSkeletons; }
        }

        /// <summary/>
        internal List<ChildSortSkeleton> ChildSortSkeletons
        {
            get { return this._childSortSkeletons; }
        }

        /// <summary/>
        public void AddPreOverride(AbstractPath path, Func<NodeExtender, object[]> preOverrideCallback)
        {
            this._preOverrideSkeletons.Add(new PreOverrideSkeleton(path, preOverrideCallback));
        }

        /// <summary/>
        public void AddPostOverride(AbstractPath path, Action<NodeExtender, List<object>> postOverrideCallback)
        {
            this._postOverrideSkeletons.Add(new PostOverrideSkeleton(path, postOverrideCallback));
        }

        /// <summary/>
        public void AddWildcardOverride(AbstractPath path, Action<NodeExtender, string, List<object>> wildcardOverrideCallback)
        {
            this._wildcardOverrideSkeletons.Add(new WildcardOverrideSkeleton(path, wildcardOverrideCallback));
        }

        /// <summary/>
        public void AddConditionalFunction(AbstractPath path, Func<NodeExtender, bool> conditionalFunctionCallback)
        {
            this._conditionalFunctionSkeletons.Add(new ConditionalFunctionSkeleton(path, conditionalFunctionCallback));
        }

        /// <summary/>
        public void AddFormattedOutputFunction(AbstractPath path, Func<NodeExtender, string> outputFunctionCallback)
        {
            this._outputFunctionSkeletons.Add(new FormattedOutputFunctionSkeleton(path, outputFunctionCallback));
        }

        /// <summary/>
        public void AddFormattedOutputsFunction(AbstractPath path, Func<NodeExtender, string[]> outputFunctionCallback)
        {
            this._outputsFunctionSkeletons.Add(new FormattedOutputsFunctionSkeleton(path, outputFunctionCallback));
        }

        /// <summary/>
        public void AddObserverFunction(AbstractPath path, Action<NodeExtender> observerFunctionCallback)
        {
            this._observerFunctionSkeletons.Add(new ObserverFunctionSkeleton(path, observerFunctionCallback));
        }

        /// <summary/>
        public void AddGlobalFormatter<T>(Func<object, string> formatterCallback)
        {
            this._globalFormatterSkeletons.Add(new GlobalFormatterSkeleton(typeof(T), formatterCallback));
        }

        /// <summary/>
        public void AddLocalFormatter<T>(AbstractPath path, Func<object, string> formatterCallback)
        {
            this._localFormatterSkeletons.Add(new LocalFormatterSkeleton(path, typeof(T), formatterCallback));
        }

        /// <summary/>
        public void AddSort(AbstractPath path, Func<NodeExtender, NodeExtender, int> selfSortCallback)
        {
            this._sortSkeletons.Add(new SortSkeleton(path, selfSortCallback));
        }

        /// <summary/>
        public void AddSelfSort<T>(AbstractPath path, Func<object, object, int> selfSortCallback)
        {
            this._selfSortSkeletons.Add(new SelfSortSkeleton(path, typeof(T), selfSortCallback));
        }

        /// <summary/>
        public void AddChildSort(AbstractPath path, Func<object[], object[], int> childSortCallback, params NameTypeExtender[] nameTypeExtenders)
        {
            this._childSortSkeletons.Add(new ChildSortSkeleton(path, childSortCallback, nameTypeExtenders));
        }
    }
}
